package cn.tedu.number;

import java.util.*;

/**
 * 作为程序员的小Q，他的数列和其他人的不太一样，他有2^n个数。
 * 老板问了小Q一共 m次，每次给出一个整数q_i(1 <= i <= m), 要求小Q把这些数每2^{q_i}分为一组，然后把每组进行翻转，小Q想知道每次操作后整个序列中的逆序对个数是多少呢？
 * <p>
 * 例如:
 * 对于序列1 3 4 2，逆序对有(4, 2),(3, 2),总数量为2。
 * 翻转之后为2 4 3 1，逆序对有(2, 1),(4, 3), (4, 1), (3, 1),总数量为4。
 * <p>
 * 输入描述:
 * 第一行一个数n(0 <= n <= 20)
 * 第二行2^n个数，表示初始的序列(1 <= 初始序列 <= 10^9)
 * 第三行一个数m(1 <= m <= 10^6)
 * 第四行m个数表示qi(0 <= {q_i} <= n)
 * <p>
 * 输出描述:
 * m行每行一个数表示答案。
 * <p>
 * 输入例子1:
 * 2
 * 2 1 4 3
 * 4
 * 1 2 0 2
 * <p>
 * 输出例子1:
 * 0
 * 6
 * 6
 * 0
 * <p>
 * 例子说明1:
 * 初始序列2 1 4 3
 * 2^{q_1} = 2 ->
 * 第一次：1 2 3 4 -> 逆序对数为0
 * 2^{q_2} = 4 ->
 * 第二次：4 3 2 1 -> 逆序对数为6
 * 2^{q_3} = 1 ->
 * 第三次：4 3 2 1 -> 逆序对数为6
 * 2^{q_4} = 4 ->
 * 第四次：1 2 3 4 -> 逆序对数为0
 */
public class ReversePair {
    private static long[] arrmv;
    private static long[] cnt;
    private static long[] max_c;

    private static void merge_sort(int pos, int sz) {
        if (sz == 0) return; // 递归的终点
        int nsz = (1 << (sz - 1));    // 区间从中间切开
        int m = pos + nsz;             // 另一边merge sort的起点
        merge_sort(pos, sz - 1);
        merge_sort(m, sz - 1);
        long[] tmp = new long[1 << sz]; // 暂存merge sort结果
        int l1 = 0, l2 = 0;
        int tpoi = 0;
        while (l1 < nsz && l2 < nsz) {
            if (arrmv[pos + l1] <= arrmv[m + l2]) {
                tmp[tpoi++] = arrmv[pos + l1];
                l1++;
            } else {
                tmp[tpoi++] = arrmv[m + l2];
                cnt[sz] += m - (l1 + pos);
                l2++;  //cnt[sz]表示2^sz 下的逆序对有多少个.
            }
        }

        while (l1 < nsz) {
            tmp[tpoi++] = arrmv[pos + l1];
            l1++;
        }
        while (l2 < nsz) {
            tmp[tpoi++] = arrmv[m + l2];
            l2++;
        }
        // 完成tmp的填充

        l1 = 0;
        l2 = 0;
        while (l1 < nsz && l2 < nsz) {
            if (arrmv[pos + l1] < arrmv[m + l2])
                l1++;
            else if (arrmv[pos + l1] > arrmv[m + l2])
                l2++;
            else {
                int cnt1 = 0, cnt2 = 0;
                while (l1 < nsz && arrmv[pos + l1] == arrmv[m + l2]) {
                    cnt1++;
                    l1++;
                }
                while (l2 < nsz && arrmv[pos + l1 - 1] == arrmv[m + l2]) {
                    cnt2++;
                    l2++;
                }
                max_c[sz] -= cnt1 * cnt2;     // 我们找到了左右区间分别有cnt1,cnt2个相同的数，它们
                // 在反转区间并不会产生影响，在这里我们需要减掉.那么max_c[sz]剩下的对数分别表示顺序对和
                // 逆序对的个数.
            }
        }
        // 排序结果需要整合给上一层使用
        if (tmp.length >= 0) System.arraycopy(tmp, 0, arrmv, pos, tmp.length);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int tot = 1 << n;
        arrmv = new long[tot];
        cnt = new long[n + 1];
        max_c = new long[n + 1];

        for (int i = 0; i < tot; i++) {
            arrmv[i] = sc.nextLong();
        }

        for (int i = 1; i <= n; i++)
            max_c[i] = 1L << (n + i - 2L);

        // 包含顺序对，逆序对以及两两相等对.
        // 注意移位时候的1ll表示long long 型
        merge_sort(0, n);

        int nu = sc.nextInt();
        for (int ii = 0; ii < nu; ii++) {
            int sz = sc.nextInt();
            long sum = 0L;
            for (int i = 1; i <= n; i++) {
                if (i <= sz)
                    cnt[i] = max_c[i] - cnt[i]; // 受影响的区间需要把顺序对和逆序对 对调
                sum += cnt[i];
            }
            assert (sum >= 0L);
            System.out.println(sum);
        }
    }
}
